package com.siqi.hr.spring;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterDisposer;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.SqlProvider;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.Assert;

public class MyJdbcTemplate extends JdbcTemplate {
	private NativeJdbcExtractor nativeJdbcExtractor;

	@SuppressWarnings({ "rawtypes", "unchecked","unused" })
	public <T> T query(final String sql, final ResultSetExtractor<T> rse)throws DataAccessException{
	    Assert.notNull(sql, "SQL must not be null");
	    Assert.notNull(rse, "ResultSetExtractor must not be null");
	    long time = System.currentTimeMillis();
	    Object t = execute(new StatementCallback(){
	        public T doInStatement(Statement stmt)throws SQLException{
	        	ResultSet rs = null;
		        try {
		            rs = stmt.executeQuery(sql);
		            ResultSet rsToUse = rs;
		            if (MyJdbcTemplate.this.nativeJdbcExtractor != null) {
		            	rsToUse = MyJdbcTemplate.this.nativeJdbcExtractor.getNativeResultSet(rs);
		           }
		           return rse.extractData(rsToUse);
		        }finally {
		            JdbcUtils.closeResultSet(rs);
		        }
	        }

	        public String getSql() { return sql; }
	    });
	    System.out.println("Executing SQL query " + (System.currentTimeMillis() - time) + "ms [" + sql + "]");
	    return (T) t;
	  }
      
	  @SuppressWarnings({ "rawtypes", "unchecked"})
	  public <T> T query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)throws DataAccessException{
	      Assert.notNull(rse, "ResultSetExtractor must not be null");
	      long time = System.currentTimeMillis();
	      Object t = execute(psc, new PreparedStatementCallback() {
	      public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
	          ResultSet rs = null;
	          try {
		          if (pss != null) {
		            pss.setValues(ps);
		          }
		          rs = ps.executeQuery();
		          ResultSet rsToUse = rs;
		          if (MyJdbcTemplate.this.nativeJdbcExtractor != null) {
		            rsToUse = MyJdbcTemplate.this.nativeJdbcExtractor.getNativeResultSet(rs);
		          }
		          return rse.extractData(rsToUse);
	          }finally {
		          JdbcUtils.closeResultSet(rs);
		          if ((pss instanceof ParameterDisposer))
		        	  ((ParameterDisposer)pss).cleanupParameters();
	          }
	      }
	    });
	    System.out.println("Executing SQL query " + (System.currentTimeMillis() - time) + "ms [" + getSql(psc) + "]");

	    return (T) t;
	  }

	  public static String getSql(Object sqlProvider){
		  if ((sqlProvider instanceof SqlProvider)) {
	          return ((SqlProvider)sqlProvider).getSql();
	      }

	      return null;
	  }
}
